package org.helyx.gae.getabike.provider;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.helyx.gae.getabike.content.accessor.ContentAccessor;
import org.helyx.gae.getabike.content.provider.ContentProvider;
import org.helyx.gae.getabike.content.provider.exception.ContentProviderException;
import org.helyx.gae.getabike.model.City;
import org.helyx.gae.getabike.model.Station;
import org.helyx.gae.getabike.provider.normalizer.StationInfoNormalizer;
import org.helyx.gae.getabike.registry.Registry;
import org.helyx.gae.util.stream.InputStreamProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

public abstract class AbstractStationContentProvider implements ContentProvider<List<Station>>, InitializingBean {

	private static final Logger LOGGER = LoggerFactory.getLogger(AbstractStationContentProvider.class);

	protected Registry<String, StationInfoNormalizer> stationInfoNormalizerRegistry;
	protected City city;
	protected ContentAccessor contentAccessor;

	public AbstractStationContentProvider() {
		super();
	}

	public void setStationInfoNormalizerRegistry(Registry<String, StationInfoNormalizer> stationInfoNormalizerRegistry) {
		this.stationInfoNormalizerRegistry = stationInfoNormalizerRegistry;
	}

	public Registry<String, StationInfoNormalizer> getStationInfoNormalizerRegistry() {
		return stationInfoNormalizerRegistry;
	}

	public void setCity(City city) {
		this.city = city;
	}

	public void setContentAccessor(ContentAccessor contentAccessor) {
		this.contentAccessor = contentAccessor;
	}
	
	public City getCity() {
		return city;
	}

	public ContentAccessor getContentAccessor() {
		return contentAccessor;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		Assert.notNull(city, "[Assertion failed] - city is required; it must not be null");
		Assert.notNull(contentAccessor, "[Assertion failed] - contentAccessor is required; it must not be null");
		Assert.notNull(stationInfoNormalizerRegistry, "[Assertion failed] - stationInfoNormalizerRegistry is required; it must not be null");
	}

	public StationInfoNormalizer getStationInfoNormalizer() {
		return stationInfoNormalizerRegistry.get(city.getKey());
	}

	public List<Station> getContent() throws ContentProviderException {
		
		InputStream inputStream = null;
		InputStreamProvider inputStreamProvider = null;
		
		try {

			List<Station> stationList = new ArrayList<Station>();
			
			try {
				
				inputStreamProvider = contentAccessor.getInputStreamProvider();
				inputStream = new BufferedInputStream(inputStreamProvider.createInputStream(true));

				stationList = getStationList(inputStream);
			}
			finally {
				inputStreamProvider.dispose();
			}

			return stationList;
			
		}
		catch (Exception e) {
    		LOGGER.warn(e.getMessage(), e);
			throw new ContentProviderException(e);
		}

	}

	protected abstract List<Station> getStationList(InputStream inputStream) throws ContentProviderException;
	
}
